package com.shyroke.daydayzhuansvc.service.impl;

import cn.hutool.core.util.StrUtil;
import com.querydsl.core.QueryResults;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.shyroke.daydayzhuanapi.constant.RedisKeyPrefix;
import com.shyroke.daydayzhuanapi.dto.LabelCountDto;
import com.shyroke.daydayzhuanapi.dto.LabelDto;
import com.shyroke.daydayzhuanapi.dto.LabelLabelListDto;
import com.shyroke.daydayzhuanapi.entity.LabelEntity;
import com.shyroke.daydayzhuanapi.entity.QLabelEntity;
import com.shyroke.daydayzhuanapi.entity.TypeEntity;
import com.shyroke.daydayzhuanapi.mapper.LabelMapper;
import com.shyroke.daydayzhuandao.respository.LabelRepository;
import com.shyroke.daydayzhuandao.respository.ProjectLabelRepository;
import com.shyroke.daydayzhuansvc.service.ILableService;
import com.shyroke.daydayzhuansvc.util.Page;
import com.shyroke.daydayzhuansvc.util.RedisUtils;
import com.shyroke.daydayzhuansvc.util.TabelData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author youhj
 * @date 2019/9/26 0026 下午 1:23
 */
@Service
public class LableService implements ILableService {

    @Autowired
    private LabelRepository labelRepository;
    @Autowired
    private ProjectLabelRepository projectLabelRepository;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private JPAQueryFactory factory;
    @Autowired
    private LabelMapper labelMapper;

    @Override
    public List<LabelDto> getHotkeyList() {
        List<LabelDto> hotKeyList= RedisUtils.readList(RedisKeyPrefix.HOTKEY);
        if(CollectionUtils.isEmpty(hotKeyList)){
            hotKeyList = this.getHotKey();
            redisTemplate.opsForValue().set(RedisKeyPrefix.HOTKEY,hotKeyList);
        }

        return hotKeyList;
    }

    @Override
    public TabelData<LabelLabelListDto> getTableData(Page page, LabelDto label) {
        QLabelEntity qLabelEntity = QLabelEntity.labelEntity;
        JPAQuery<LabelEntity> query = factory.selectFrom(qLabelEntity);
        if(StrUtil.isNotBlank(label.getLabelName())){
            query = query.where(qLabelEntity.labelName.like("%"+label.getLabelName()+"%"));
        }
        if(label.getTypeId() != null) {
            query = query.where(qLabelEntity.type.id.eq(label.getTypeId()));
        }

        QueryResults<LabelEntity> queryResults = query
                .offset(PageRequest.of(page.getPage() - 1, page.getLimit()).getOffset()).limit(page.getLimit())
                .orderBy(qLabelEntity.isShowTitle.asc())
                .fetchResults();

        List<LabelLabelListDto> list = queryResults.getResults().stream().map(e -> labelMapper.entityToAdminDto(e)).collect(Collectors.toList());

        return new TabelData<LabelLabelListDto>(list,(int)queryResults.getTotal());
    }

    @Override
    public LabelEntity findByLableName(String labelName) {
        return labelRepository.findByLabelName(labelName);
    }

    @Override
    public void save(LabelEntity label) {
        labelRepository.save(label);
    }

    @Override
    public void saveOne(LabelDto label) {
        LabelEntity entity = new LabelEntity();
        entity.setLabelName(label.getLabelName());
        entity.setKeys(label.getKeys());
        entity.setIsShowTitle(label.getIsShowTitle());
        if(label.getTypeId() != null) {
            TypeEntity type = new TypeEntity();
            type.setId(label.getTypeId());
            entity.setType(type);
        }

        labelRepository.save(entity);
    }

    private List<LabelDto> getHotKey() {
        List<Map<String,Integer>> mapList = labelRepository.findByLabelCount();
        if(mapList.isEmpty()){
            return null;
        }
        List<LabelCountDto> result = mapList.stream().map(m -> {
            Integer labelid = m.get("labelid");
            Integer count = m.get("count");
            LabelCountDto dto = new LabelCountDto();
            dto.setLabelid(labelid);
            dto.setCount(count);
            return dto;
        }).collect(Collectors.toList());
        List<Integer> labelIdList = result.stream().map(dto -> dto.getLabelid()).collect(Collectors.toList());
        Map<Integer,Integer> countMaps = new HashMap<>();
        for (LabelCountDto labelCountDto : result) {
            countMaps.put(labelCountDto.getLabelid(),labelCountDto.getCount());
        }
        List<LabelEntity> labelList = labelRepository.findByIdIn(labelIdList);
        Map<Integer,LabelEntity> maps = new HashMap<>();
        for (LabelEntity labelEntity : labelList) {
            maps.put(labelEntity.getId(),labelEntity);
        }
        return  result.stream().map(dto -> {
            Integer labelid = dto.getLabelid();
            Integer count = countMaps.get(labelid);
            LabelEntity labelEntity = maps.get(labelid);
            LabelDto labelDto = new LabelDto();
            labelDto.setCount(count);
            labelDto.setLabelName(labelEntity.getLabelName());
            labelDto.setKeys(labelEntity.getKeys());
            labelDto.setId(labelEntity.getId());
            labelDto.setIsShowTitle(labelEntity.getIsShowTitle());
            return labelDto;
        }).collect(Collectors.toList());
    }

    @Async
    public void updateCount(String key) {
        LabelEntity label = labelRepository.findByLabelName(key);
        if(label != null){
            Integer count = label.getReadCount()==null?0:label.getReadCount();
            label.setReadCount(++count);
            labelRepository.save(label);
        }
    }

    public List<LabelEntity> findByIdIn(List<Integer> labelIds) {
        return labelRepository.findByIdIn(labelIds);
    }
}
